#include "Socket.h"

Socket::Socket(uint16_t port)
{
    m_fd = socket(AF_INET, SOCK_STREAM, 0);
    setReuseAddr(1);
    setKeepAlive(1);
    if (m_fd == -1)
    {
        perror("socket error!");
        return;
    }
    InetAddress localAddr(port);
    bindAddress(localAddr);
    listen();
}

Socket::~Socket()
{
    close(m_fd);
}
void Socket::bindAddress(InetAddress &localAddr)
{
    if (::bind(m_fd, (sockaddr *)localAddr.getSockAddr(), sizeof(sockaddr_in)) != 0)
    {
        perror("bind error!");
    }
}
void Socket::listen(int num)
{
    if (::listen(m_fd, num) != 0)
    {
        perror("listen error!");
    }
}
int Socket::accept(InetAddress *peerAddr)
{
    sockaddr_in addr;
    socklen_t socklen = sizeof(addr);
    // int fd = ::accept4(m_fd, (sockaddr *)&addr, &socklen, SOCK_CLOEXEC | SOCK_NONBLOCK);
    int fd = ::accept(m_fd, (sockaddr *)&addr, &socklen);
    if (fd >= 0)
    {
        if(peerAddr != nullptr) {
            peerAddr->setSockAddr(addr);
        }
    }
    else
    {
        perror("accept4 error!");
    }
    return fd;
}

void Socket::setReuseAddr(bool on) {
    int optval = on ? 1 : 0;
    setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
}
void Socket::setReusePort(bool on) {
    int optval = on ? 1 : 0;
    setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
}
void Socket::setKeepAlive(bool on) {
    int optval = on ? 1 : 0;
    setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
}